package com.mec.beans.y2013.m03;

import java.io.File;
import java.io.IOException;

import org.apache.commons.fileupload.FileItem;
import org.apache.log4j.Logger;

import com.mec.beans.y2013.util.FilePathUtil;
import com.mec.beans.y2013.util.FileUploadUtil;
import com.mec.exception.y2013.m03.FileSaveFailedException;

/**
 * A simple File upload handler;
 * @author MEC
 * @since 2013-03-30
 *
 */
public class FileUploadHandler {

	/**
	 * Default fileUploadHandler constructor;
	 */
	public FileUploadHandler(){
		
	}
	public FileUploadHandler(String parentDir, String subDir, int randSuffixLength){
		this.parentDir = parentDir;
		this.subDir = subDir;
		this.randSuffixLength = randSuffixLength;
	}
	
	public void processUploadedFile(FileItem item) 
			throws FileSaveFailedException, IOException, Exception{
		processUploadedFile(item, 
				this.parentDir, 
				this.subDir,
				this.randSuffixLength
				);
	}
	
	/*
	public static FileUploaderHandler getInstance(){
		return instance;
	}*/
	/**
	 * Save the FileItem file on server;
	 * @param item the FileItem object to save on server;
	 * @param parentDir parent Directory to store uploaded file, usually the servlet Context path;
	 * @param subDir sub directory to store the uploaded file, usually the value specified in web.xml 
	 * @param randSuffixLength length of the random suffix string appended to the original file name;
	 * @throws Exception
	 */
	public void processUploadedFile(FileItem item, 
			String parentDir, 
			String subDir, 
			int randSuffixLength) 
					throws FileSaveFailedException, IOException, Exception{
		//String fieldName = item.getFieldName();
		String fileName = item.getName();
		//String contentType = item.getContentType();
		long sizeInBytes = item.getSize();
		//
		
		/*
		 * since ServletFileUpload has messed with 
		 * the request.inputStream, you probably won't 
		 * get what you want here through request.parameter("").
		 * 
		 * However, you can get normal form fields info
		 * through FileItem.fieldName & FileItem.string
		 * (if FileItem.formField == true) ;
		 * 
		 * refer to HttpServletRequest.getParameter(*) doc;
		 */
		//String newName = request.getParameter("newName");
		//
		
		String currentPath = getFileName(fileName, parentDir, subDir, randSuffixLength);
		//logger.info(fileName +" uploaded from browser will be saved in " +currentPath);
		//
		//logger.info("UploadedFile -> " + currentPath);
		File uploadedFile = new File(currentPath);
		if( ! uploadedFile.exists()){
			File parentFolder = uploadedFile.getParentFile();
			if(!parentFolder.exists()){
				parentFolder.mkdirs();
			}
			uploadedFile.createNewFile();
		}else{
			throw new FileSaveFailedException("File already exists: " + currentPath);
		}
		item.write(uploadedFile);
		
		logger.info("File saved on server: " + uploadedFile);
		//request.setAttribute("uploadedFile", currentPath);
	}
	

	
	/**
	 * Get userLocalFileName and returns serverFileName;
	 * INPUT:
	 * 	1, c:\Users\\user-name\I\mages\\img-1.jpg, var/www/test_web/, upload
	 * 	2, /home/user-name/pictures/img-1.jpg, c:\www\test_web\, upload
	 *  3, 
	 * returns:
	 * 	1, ${CATALINA_HOME}/webapps/test_web/uploaded/2013/03/29/img-1.jpg
	 * 	2, 
	 * OUTPUT:
	 * @param originalName local file name from user's computer;
	 * @param serverAppRealPath Servlet Context Path on server;
	 * @param serverUserUploadPath Server directory to hold the user uploaded contents;
	 * @return
	 */
	private String getFileName(String originalName, 
			String serverAppRealPath, 
			String serverUserUploadPath,
			int randSuffixLength
			){
		//
		/*
		logger.info("newName -> " + newName);
		if(isImage(originalName.toUpperCase())){
			request.setAttribute("isImage",	true);
			//logger.info("original File is Image");
		}*/
		
		//logger.info("originalName ->" + originalName);
		//ServletContext application = request.getServletContext();
		
		//String retval = application.getRealPath("/");
		//String serverPathOfFile = application.getInitParameter(WebXMLConfig2013.USER_UPLOAD_ROOT_PATH);
		String retval = serverAppRealPath;
		String serverPathOfFile = serverUserUploadPath;
		serverPathOfFile += pathUtil.wrapAsFilePath(upUtil.getDateAsPath());
		//logger.info("[1] -> " + serverPathOfFile);
	
		//extract filename.extension from original file name
		//remove the parent directory part;
		//e.g. 
		//input: /home/user-name/pic-1.jpg;
		//output: pic-1.jpg
			int index = originalName.lastIndexOf(File.separatorChar);
			if( -1 < index){
				serverPathOfFile += originalName.substring(index);
			}else{
				serverPathOfFile += originalName;
			}
			
		//}
		serverPathOfFile = appendRandSuffix(serverPathOfFile, randSuffixLength);
		//request.setAttribute("referencePath", serverPathOfFile);
		setUploadedFilePath(serverPathOfFile);
		//logger.info("[2] -> " + serverPathOfFile);
		
		retval += serverPathOfFile;
		//logger.info("new File Name -> " +file);
		
		return retval;
	}
	

	
	
	/**
	 * 
	 * Note: 
	 * 1, the return value is without servletContext.contextPath;
	 * e.g. if a file "img-1.jpg" is uploaded to "/test_web/upload/2013/03/30/img-1.jpg", 
	 * then this method would return /upload/2013/03/30/img-1/jpg; that's it;
	 * 2, call this method after the processUploadedFile() has been called;
	 * 	or the return value will be the last uploaded file's;
	 * @return path of the lasted uploaded file on server; or null if no 
	 * 	file has been uploaded; 
	 */
	public String getUploadedFilePath() {
		return uploadedFilePath;
	}

	private void setUploadedFilePath(String uploadedFilePath) {
		this.uploadedFilePath = uploadedFilePath;
	}

	/**
	 * Append random string suffix to the original file name;
	 * @param origin
	 * @return
	 */
	private String appendRandSuffix(String origin, int randSuffixLength){
		return pathUtil.genRandomFileName(origin, randSuffixLength);
	}
	

	private String uploadedFilePath; //file path on server, without contestPath;
	
	private int randSuffixLength; //random string suffix length;
	private String parentDir;	//usually the Servlet Context Path;
	private String subDir;	// usually the upload directory specified in web.xml;
	
	private FilePathUtil pathUtil = FilePathUtil.getInstance();
	private FileUploadUtil upUtil = FileUploadUtil.getInstance();
	/*private static final FileUploaderHandler instance = new FileUploaderHandler();*/
	private static final Logger logger = Logger.getLogger(FileUploadHandler.class);
}
